home *** CD-ROM | disk | FTP | other *** search
/ NeXT Enterprise Objects Framework 1.1 / NeXT Enterprise Objects Framework 1.1.iso / NextDeveloper / Examples / EnterpriseObjects / MasteringDetails / EOFExtensions.subproj / RelationshipKeySetter.m < prev    next >
Encoding:
Text File  |  1995-02-18  |  7.7 KB  |  206 lines

  1. /* RelationshipKeySetter.m created by cfeder on Tue 08-Nov-1994 */
  2.  
  3. #import "RelationshipKeySetter.h"
  4. #import "ValueForKey.h"
  5. #import <objc/objc-runtime.h>
  6.  
  7. @implementation EOEntity (attrsNamed)
  8. - attributesNamed:(NSArray *)names
  9. {
  10.     int i, count = [names count];
  11.     NSMutableArray *result = [NSMutableArray arrayWithCapacity:count];
  12.     for(i=0; i<count; i++) {
  13.         EOAttribute *attr = [self attributeNamed:[names objectAtIndex:i]];
  14.         if (attr)
  15.             [result addObject:attr];
  16.     }
  17.     return result;
  18. }
  19.  
  20. - createObject
  21. {
  22.     id eo = nil;
  23.     const char *className  = [self className];
  24.     Class eoClass = objc_lookUpClass (className);
  25.  
  26.     if (!eoClass) eoClass = [EOGenericRecord class];
  27.  
  28.     if (eoClass) {
  29.         eo = [eoClass allocWithZone:[self zone]];
  30.         if ([eo respondsToSelector:@selector(initWithPrimaryKey:entity:)])
  31.             eo = [eo initWithPrimaryKey:nil entity:self];
  32.         else
  33.             [eo init];
  34.     }
  35.     return [eo autorelease];
  36. }
  37. @end
  38.  
  39.  
  40. @implementation EORelationship (setPropsInDestObject)
  41. - (NSArray *)sourceKeys
  42. {
  43.     EORelationship *sourceRelationship = [self isFlattened]
  44.         ? [[self componentRelationships] objectAtIndex:0] : self;
  45.     NSArray *joins = [sourceRelationship joins];
  46.     int i, count = [joins count];
  47.     NSMutableArray *results = [NSMutableArray arrayWithCapacity:count];
  48.  
  49.     for (i = 0; i < count; i++) {
  50.         EOJoin *join = [joins objectAtIndex:i];
  51.         [results addObject:[[join sourceAttribute] name]];
  52.     }
  53.     return results;
  54. }
  55.  
  56. - (void)setJoinPropertiesInDestinationObject:destination fromSourceObject:source
  57. {
  58.     NSArray *joins = [self joins];
  59.     int i, count = [joins count];
  60.  
  61.     for (i = 0; i < count; i++) {
  62.         EOJoin *join = [joins objectAtIndex:i];
  63.         id val = [(NSObject *)source valueForKey:[[join sourceAttribute] name]];
  64.         if (!val) val = [EONull null];
  65.         [destination takeValue:val forKey:[[join destinationAttribute] name]];
  66.     }
  67. }
  68.  
  69. - (void)setJoinPropertiesInSourceObject:source fromDestinationObject:destination
  70. {
  71.  
  72.     NSArray *joins = [self joins];
  73.     int i, count = [joins count];
  74.  
  75.     for (i = 0; i < count; i++) {
  76.         EOJoin *join = [joins objectAtIndex:i];
  77.         id val = [(NSObject*)destination valueForKey:[[join destinationAttribute] name]];
  78.         if (!val) val = [EONull null];
  79.         [source takeValue:val forKey:[[join sourceAttribute] name]];
  80.     }
  81. }
  82.  
  83. - (NSDictionary *)destinationValuesFromSourceObject:sourceObject
  84. {
  85.     NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];
  86.     [self setJoinPropertiesInDestinationObject:dictionary fromSourceObject:sourceObject];
  87.     return dictionary;
  88. }
  89.  
  90. - (BOOL)hasJoinsOnPrimaryKeyOfSourceEntity
  91. {
  92.     // FIX ME!
  93.     // this is not quite right for multi-attribute keys (the ordering may
  94.     // cause a false mismatch)
  95.     return [[self sourceKeys] isEqual:[[self entity] primaryKeyAttributeNames]];
  96. }
  97.  
  98. - (void)updateMasterObject:master withNewDestinationObject:destination
  99.     // For to-one relationships!
  100. {
  101.     // Decide which way to propagate the attributes based on which side of the
  102.     // relationship hooks to a primary key.
  103.     if ([self hasJoinsOnPrimaryKeyOfSourceEntity])
  104.         [self setJoinPropertiesInDestinationObject:destination fromSourceObject:master];
  105.     else
  106.         [self setJoinPropertiesInSourceObject:destination fromDestinationObject:master];
  107. }
  108.  
  109. - linkObjectForSourceObject:master destinationObject:destination
  110.     // created an intermediate object for many-to-many relationship through
  111.     // an intermediate table.  Initializes keys of intermediate object using
  112.     // keys from source and destination object
  113. {
  114.     NSArray *relationships = [self componentRelationships];
  115.     EORelationship *sourceToLink = [relationships objectAtIndex:0];
  116.     EORelationship *linkToDestination = [relationships objectAtIndex:1];
  117.     EOEntity *linkEntity = [sourceToLink destinationEntity];
  118.     id link = [linkEntity createObject];
  119.     [sourceToLink setJoinPropertiesInDestinationObject:link fromSourceObject:master];
  120.     [linkToDestination setJoinPropertiesInSourceObject:link fromDestinationObject:destination];
  121.     return link;
  122. }
  123.  
  124. - updateKeysForSourceObject:source destinationObject:destination
  125.     // Sets keys on source or destination to maintain consistency for
  126.     // the source to now map to destination for this relationship.
  127.     // Does not actually assign destination to ivar in source (just messes
  128.     // with the keys).
  129.     // Returns the modified object (source or destination). In the case of
  130.     // a many to many returns a newly created link object.
  131.     // The caller is reposible for inserting or updating the returned
  132.     // object in the database.
  133. {
  134.     id modifiedObject = nil;
  135.     
  136.     if ([self isToMany]) {
  137.         // figure out what values we need to snarf from our parents
  138.         if ([self isFlattened]) {
  139.             // Many to many   create link obj          Delete link   none     to-many
  140.             // I'm assuming there's only one link object...
  141.             modifiedObject = [self linkObjectForSourceObject:source destinationObject:destination];
  142.         } else {
  143.             // PK -> FK       D->FK := M->PK           none          none     to-many
  144.             [self setJoinPropertiesInDestinationObject:destination fromSourceObject:source];
  145.             modifiedObject = destination;
  146.         }
  147.     } else {
  148.         if ([self hasJoinsOnPrimaryKeyOfSourceEntity]) {
  149.             // PK -> PK       D->PK := M->PK           None          none     to-one
  150.             [self setJoinPropertiesInDestinationObject:destination fromSourceObject:source];
  151.             modifiedObject = destination;
  152.         } else {
  153.             // FK -> PK       M->FK := D->PK           M->FK=NULL    none     to-one
  154.             // We need to update the master with a new foreign key.
  155.             // send it to the dataSource as well...
  156.             [self setJoinPropertiesInSourceObject:source fromDestinationObject:destination];
  157.             modifiedObject = source;
  158.         }
  159.     }
  160.     return modifiedObject;
  161. }
  162.  
  163.  
  164. - updateKeysForDeleteOfDestinationObject:destination fromSourceObject:source
  165.     // Sets keys on source or destination to maintain consistency for
  166.     // a delete of the destination from the source.  Returns the object
  167.     // modified, or a synthesized link object that must be deleted to
  168.     // affect the delete.  The caller is responsible for updating the
  169.     // source object, or deleting the destination or link in the database.
  170.     //
  171.     // This does not actually update destination to ivar in source (just messes
  172.     // with the keys).
  173. {
  174.     id modifiedObject = nil;
  175.  
  176.     if ([self isToMany]) {
  177.         // figure out what values we need to snarf from our parents
  178.         if ([self isFlattened]) {
  179.             // Many to many   create link obj          Delete link            to-many
  180.             // I'm assuming there's only one link object...
  181.             modifiedObject = [self linkObjectForSourceObject:source destinationObject:destination];
  182.         } else {
  183.             // PK -> FK       D->FK := M->PK           Delete D               to-many
  184.             // Nil out foreign key in destination
  185.             [self setJoinPropertiesInDestinationObject:destination fromSourceObject:nil];
  186.             modifiedObject = destination;
  187.         }
  188.     } else {
  189.         if ([self hasJoinsOnPrimaryKeyOfSourceEntity]) {
  190.             // PK -> PK       D->PK := M->PK           delete D               to-one
  191.             // no use nilling out destinations primary key.  Row must be deleted
  192.             modifiedObject = destination;
  193.         } else {
  194.             // FK -> PK       M->FK := D->PK           M->FK=NULL             to-one
  195.             // nil out foreign key in source
  196.             [self setJoinPropertiesInSourceObject:source fromDestinationObject:nil];
  197.             modifiedObject = source;
  198.         }
  199.     }
  200.     return modifiedObject;
  201. }
  202.  
  203. @end
  204.  
  205.  
  206.